package com.acme.bankapp.domain.bank;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import com.acme.bankapp.domain.bank.exception.ClientExistsException;

/**
 * Bank.
 * 
 */
public class Bank {
	private transient List<ClientRegistrationListener> listeners = new ArrayList<ClientRegistrationListener>();

	private Set<Client> clients = new LinkedHashSet<Client>();

	/**
	 * Adds new client to the bank.
	 * 
	 * @param client
	 *            client to add
	 * @throws ClientExistsException
	 */
	public void addClient(Client client) throws ClientExistsException {
		if (!clients.contains(client)) {
			clients.add(client);
			fireClientAdded(client);
		} else {
			throw new ClientExistsException();
		}
	}

	/**
	 * Returns all clients of the bank.
	 * 
	 * @return set of clients
	 */
	public Set<Client> getClients() {
		return new LinkedHashSet<Client>(clients);
	}

	/**
	 * Returns all accounts in the bank.
	 * 
	 * @return set of accounts
	 */
	public Set<Account> getAccounts() {
		Set<Account> accounts = new LinkedHashSet<Account>();

		for (Client client : clients) {
			accounts.addAll(client.getAccounts());
		}

		return accounts;
	}

	private void fireClientAdded(Client client) {
		for (ClientRegistrationListener listener : listeners) {
			listener.onClientAdded(client);
		}
	}

	/**
	 * Adds new client registration listener to bank instance.
	 * 
	 * @param listener
	 *            listener
	 */
	public void addClientRegistrationListener(
			ClientRegistrationListener listener) {
		listeners.add(listener);
	}

	/**
	 * Listener class sending e-mail notification when client is added.
	 * 
	 */
	public class EmailNotificationListener implements
			ClientRegistrationListener {
		public void onClientAdded(Client client) {
			System.out.println("[LISTENER] Notification email for client "
					+ client.getClientSalutation() + " to be sent.");
		}
	}

	/**
	 * Listener class printing notification to the console when client is added.
	 * 
	 */
	public class PrintClientListener implements ClientRegistrationListener {
		public void onClientAdded(Client client) {
			System.out.println("[LISTENER] Client "
					+ client.getClientSalutation() + " is added.");

		}
	}

	/**
	 * Looks for an equal client in the bank.
	 * 
	 * @param client
	 *            client object to compare with
	 * @return client already existing in the bank, or null if none
	 */
	public Client locateClient(Client client) {
		for (Client bankClient : getClients()) {
			if (bankClient.equals(client)) {
				return bankClient;
			}
		}
		return null;
	}
}
